<template>
  <div class="greetings">
    <h1>我是hello组件</h1>
    <Suspense>
      <template v-slot:default>
        <Person message="很开心啊" ref="helloChild" :getChild="childInfo" @haha="childInfo2" />
      </template>
    </Suspense>
    <div>
      <span>姓名：{{ name }}</span>
      <span style="margin-left: 30px">年龄：{{ age }}</span>
      <button style="margin-left: 30px" @click="change('你好所示')">改名改年龄</button><br />
    </div>

    <div>
      <span>通过计算属性得到全名：{{ fullName }}</span>
      <button style="margin-left: 30px" @click="change0">通过计算属性改全名</button><br />
    </div>

    <div>
      <span>车辆品牌：{{ person1.car }}</span>
      <span style="margin-left: 30px">车辆大小：{{ person1.size }}</span>
      <span style="margin-left: 30px">车辆品牌：{{ person2.car }}</span>
      <span style="margin-left: 30px">车辆大小：{{ person2.size }}</span>
      <button style="margin-left: 5px" @click="changeperson">改车辆</button>
    </div>

    <button @click="change1">修改1(toref)</button><br />
    <button @click="change2">修改2(torefs)</button><br />
  </div>
</template>

<!-- 这个暂时就不用了，名字在下面指出了
<script lang="ts">
  export default {
    name: 'Hello_V'
}
</script> -->

<script setup lang="ts" name="Hello_V">
//用setup的第二种写法
//注意： <script> and <script setup> must have the same language type.也就是说要么都不写lang，要写就都写
import { computed, reactive, ref, toRef, toRefs, watch, watchEffect, Suspense } from 'vue'
import Person from './Person.vue'

let helloChild = ref()
let name = ref('李四')
let age = ref('12')

let person1 = ref({
  car: '大众',
  size: 'large'
})
let person2 = reactive({
  car: '奔驰',
  size: 'mini'
})

const childInfo = (value: any) => {
  console.log('获取到子组件传递过来的值1', value)
}

const childInfo2 = (value: any) => {
  console.log('获取到子组件传递过来的值2', value)
}
//computed写法一：这么定义的计算属性是只读的，无法修改fullName的值
// const fullName = computed(() => {
//   return `${name.value} ${age.value}`
// })

//computed写法二：可读可写
const fullName = computed({
  get() {
    return `${name.value} ${age.value}`
  },
  set(val) {
    let srr = val.split('-')
    name.value = srr[0]
    age.value = srr[1]
  }
})

//情况一：(1)监视ref定义的基本类型
const stopWatch = watch(name, (newvalue, oldvalue) => {
  console.log('有人修改了name值', newvalue, oldvalue)
  // if (!name.value) {
  //   stopWatch() //还可以设置停止监听，很神奇！！！！！！
  // }
})

//情况一：(2)监视ref定义的对象类型，是监测不到的，因为监测的是对象地址值，需要手动开启深度监听才行
//注意：当只是修改对象的某个属性的值，虽然是可以检测到，但是新旧值却是一样的，因为新值是要去新的地址值取的，地址值不变则不变
watch(
  person1,
  (newvalue, oldvalue) => {
    console.log('有人修改了person1对象', newvalue, oldvalue)
  },
  {
    deep: true, //加上他才可以检测ref定义的对象的某个属性，否则只有修改person1直接赋值新的才可以检测到
    immediate: true
  }
)
//情况二：监视reactive定义的对象类型是可以检测到的
watch(person2, (newvalue, oldvalue) => {
  console.log('有人修改了person2对象', newvalue, oldvalue)
})

//情况三：监视对象的某个属性，需要第一个参数传入一个函数返回值，你修改其他属性就不会被当前这个watch监视到
watch(
  () => person2.car,
  (newvalue, oldvalue) => {
    console.log('有人修改了person2的car属性', newvalue, oldvalue)
  }
)

watchEffect(() => {
  if (name.value == '李四111' || age.value == '12111') {
    console.log('watcheffect监听到了变化')
  }
})
function changeperson() {
  //直接赋值新旧值才会改变，否则可能是一样的
  person1.value = {
    car: '大众新版',
    size: 'large_plus'
  }
  // person2 = {
  //   car: '奔驰幻影',
  //   size: 'mini_plus'
  // }

  // person1.value.car += '1'
  person2.car += '1'
  // person2.size += '1'
}

function change0() {
  fullName.value = '李五-22'
}

function change(data: any) {
  console.log(data)
  age.value += '1'
  name.value += '1'
  console.log('hello中的ref组件实例', helloChild.value)
}

function change1() {
  // name = ref('王五') //这样是不会更新界面的
  let newName = name.value
  console.log('name-1', newName)

  let newName2 = toRef(name.value)
  console.log('name-2', newName2)
  newName2.value = '王五' //newName虽然也是响应式的了，但是原来的name还是不变的
  console.log('name-3', newName2, name)
}

function change2() {
  let newCar = person2.car
  console.log('person-1', newCar)

  // 这种和change1里面一样是改不了person里面的值的
  // let newCar2 = toRef(person.car)
  // newCar2.value = '宝马'

  // 这种是可以修改person的值的
  let newCar2 = toRefs(person2)
  newCar2.car.value = '宝马'
  console.log('person-2', newCar2, person2)
}
defineExpose({
  name,
  age,
  change1
})
</script>

<style scoped>
h1 {
  font-weight: 500;
  font-size: 2.6rem;
  position: relative;
  top: -10px;
}

h3 {
  font-size: 1.2rem;
}

.greetings h1,
.greetings h3 {
  text-align: center;
}

@media (min-width: 1024px) {
  .greetings h1,
  .greetings h3 {
    text-align: left;
  }
}
</style>
